<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.0 / SVN信息: $Id: class.JCAT_IdentityManager.php 1603 2009-03-31 15:35:42Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/
namespace JCAT ;

/**
 * 身份管理器
 *
 */
class IdentityManager implements IIdentityManager
{
	/**
	 * Description
	 *
	 * @access	public
	 * @static
	 * @return	IdentityManager
	 */
	static public function GetGlobalInstance()
	{		
		if( !self::$aGlobalInstance )
		{
			$aSession = Session::GetGlobalInstance() ;
			self::$aGlobalInstance = self::CreateInstance(self::DEFAULT_IDMGR_NAME,$aSession) ;	
		}
		
		return self::$aGlobalInstance ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$aGlobalInstance	IdentityManager
	 * @return	void
	 */
	public function SetGlobalInstance(IdentityManager $aGlobalInstance)
	{
		self::$aGlobalInstance = $aGlobalInstance ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sInsName			string
	 * @param	$aSession=null		ISession
	 * @static
	 * @return	void
	 */
	static public function CreateInstance($sInsName,ISession $aSession=null)
	{
		$sIDSessionKey = self::IDMGR_SESSIONKEY_PREFIX.$sInsName ;
		
		// create a php session
		if(!$aSession)
		{
			$aSession = Session::GetGlobalInstance() ;
		}
		
		// try get from session
		$aIDMgr = $aSession->GetVariable($sIDSessionKey) ;

		return $aIDMgr?
			$aIDMgr :											// restore object from session
			new IdentityManager($sInsName, $aSession) ;	// create new object
	}
	
	/**
	 * Description
	 *
	 * @access	protected
	 * @param	$sInsName			string
	 * @param	$aSession=null		ISession
	 * @return	void
	 */
	protected function IdentityManager($sInsName,ISession $aSession=null)
	{
		// session
		if(!$aSession)
		{
			$aSession = Session::GetGlobalInstance() ;
		}
		$this->SetSession($aSession) ;

		$this->sInsName = $sInsName ;
		
		// save to Session
		$this->sSessionKey = self::IDMGR_SESSIONKEY_PREFIX.$sInsName ;
		$aSession->SetVariable($this->sSessionKey,$this) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetName()
	{
		return $this->sInsName ;		
	}
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @return	void
	 */
	public function __sleep()
	{
		$arrParentPropertys[] = Package::MakePrivatePropertyNameForSerialize('sSessionKey',__CLASS__) ;
		$arrParentPropertys[] = Package::MakePrivatePropertyNameForSerialize('arrLoginedIdentitys',__CLASS__) ;
		
		return $arrParentPropertys ;
	}
	/**
	 * 通过身份名称取得身份
	 * 
	 * @access	public
	 * @param	$sIdentityName		string	身份名称
	 * @return	IIdentity
	 */
	public function QueryIdentity($sIdentityName)
	{
		return isset($this->arrLoginedIdentitys[$sIdentityName])?
					$this->arrLoginedIdentitys[$sIdentityName]:
					null ;
	}

	/**
	 * what's this
	 * 
	 * @access	public
	 * @param	$aIdentity		IIdentity		what's this
	 * @return	old_value
	 */
	public function IdentityLogin(IIdentity $aIdentity)
	{
		if(!$aIdentity->IsLogined())
		{
			throw new Exception(Language::SentenceEx(
				'身份：“%s”尚未完成登录，无法提交到身份管理器。'
				, 'LanguagePackage', null
				, $sIdentityName
			)) ;
		}

		// 已经存在的 身份
		$sIdentityName = $aIdentity->GetIdentityClass() ;
		if(isset($this->arrLoginedIdentitys[$sIdentityName]))
		{
			$old_value = $this->arrLoginedIdentitys[$sIdentityName] ;
			
			// 已存在 先登出
			$old_value->Logout() ;
		}
		else 
		{
			$old_value = null ;
		}
		
		$this->arrLoginedIdentitys[$sIdentityName] = $aIdentity ;
		return $old_value ;
	}
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @param	$IdentityOrName		IIdentity, string		what's this
	 * @return	void
	 */
	public function IdentityLogout( $IdentityOrName )
	{
		ASSERT::ASSERT_ISTHESE($IdentityOrName,array('string','JCAT\IIdentity'));
		
		if( GlobalFunc::HasImplementedTo($IdentityOrName,'IIdentity') )
		{
			$sIdentityName = $IdentityOrName->GetName() ;
		}
		else
		{
			$sIdentityName =& $IdentityOrName ;
			if(isset($this->arrLoginedIdentitys[$sIdentityName]))
			{
				$this->arrLoginedIdentitys[$sIdentityName]->Logout() ;
			}
		}
		
		unset( $this->arrLoginedIdentitys[$sIdentityName] ) ;
	}
	
	/**
	 * 为所有已登录的 身份对象 创建一个迭代器
	 *
	 * @access	public
	 * @return	IIterator
	 */
	public function CreateIdentityIterator()
	{
		return new ArrayIterator($this->arrLoginedIdentitys) ;
	}

	/**
	 * 设置会话对象
	 * 
	 * @access	public
	 * @param	$aSession	ISession	会话
	 * @return	old_value
	 * @see IIdentity::SetSession()
	 */
	public function SetSession(ISession $aSession)
	{		
		$old_value = $this->aSession ;
		$this->aSession = $aSession ;
		return $old_value ;
	}

	
	/**
	 * 取得会话对象
	 * 
	 * @access	public
	 * @return	ISession
	 * @see IIdentity::GetSession()
	 */
	public function GetSession()
	{
		return $this->aSession ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetSessionKey()
	{
		return $this->sSessionKey ;
	}
	
	// 属性 ////////////////////////////////////
	
	
	const DEFAULT_IDMGR_NAME = '@Default@' ;
	
	const IDMGR_SESSIONKEY_PREFIX = '__IDManger::' ;
	
	/**
	 * 已登录的身份
	 * 
	 * @access	private
	 * @var		array:IIdentity
	 * @static 
	 */
	private $arrLoginedIdentitys = array() ;
	
	/**
	 * 用于保存身份的会话类类名
	 * 
	 * @access	private
	 * @var		string
	 */
	private $aSession ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sSessionKey ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sInsName ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @static
	 * @var		array:IdentityManager
	 */
	static private $aGlobalInstance ;
}

?>
